package poland;

import java.util.*;


public class Calc {
	public class State {
		public Stack<Node> stack = new Stack<Node>();
		public double numericResult;
		public String textualResult;
		
	}
	
	private State state;
	
	public Calc() {
		state = new State();
	}
	
	public double getValue()
	{
		return state.numericResult;
	}
	
	public String getTextualValue()
	{
		return state.textualResult;
	}
	
	public boolean process(String expression) {
		state.stack.clear();
		for (String tok : expression.split(" ")) {
			if (!processToken(tok))
			{
				return false;
			}
		}
		if (state.stack.size() != 1) {
			return false;
		}
		// Populate string format
		Node node = state.stack.pop();
		state.numericResult = node.value;
		state.textualResult = node.textualValue;
		return true;
	}
	
	boolean processToken(String token) {
		if (token.length() > 0) {
			if (Character.isDigit(token.charAt(0))) {
				try {
					Double val = Double.parseDouble(token);
					Node node = new Node(val, val.toString());
					state.stack.push(node);
				}
				catch (NumberFormatException ex) {
					return false;
				}
			} else if (state.stack.size()>=2) {
				Node bNode=state.stack.pop();
				Node aNode=state.stack.pop();
				double val;
				if (token.equals("+")) {
					val = aNode.value+bNode.value; 
				} else if (token.equals("-")) {
					val = aNode.value-bNode.value;
				} else if (token.equals("*")) {
					val = aNode.value*bNode.value;
				} else if (token.equals("/") && bNode.value!=0) {
					val = aNode.value/bNode.value;
				} else if (token.equals("^")) {
					val = Math.pow(aNode.value, bNode.value);
				} else {
					return false;
				}
				state.stack.push(new Node(val, "(" + aNode.textualValue + token + bNode.textualValue + ")"));
			} else {
				return false;
			}
		}
		//dump(); // red debugging printing , prints the entire stack
		
		return true;
	}
	
	void dump() {
		System.err.print("[ ");
		for (Node e : state.stack) {
			System.err.print(e.value + " ");
		}
		System.err.println("]");
	}
	
	class Node
	{
		double value;
		String textualValue;
		public Node(double value, String textualValue){
			this.value = value;
			this.textualValue = textualValue;
		}
	}
}
